package com.audaque.springboot.foshanupload.amqp.config;


import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.concurrent.ListenableFutureCallback;

@Slf4j
@Configuration
public class ReturnConfirmCallbackConfig implements ApplicationContextAware {
  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
	// 获取RabbitTemplate
	RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
	// 设置ReturnCallback(回调)
	rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
	  @Override
	  public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
		log.debug("收到消息的return callback, exchange:{},key:{}, msg:{}, code:{},text:{}",
		exchange, routingKey, message, replyCode, replyText);
	  }

	});
  }


  @Bean
  public CorrelationData correlationData() {
	// 1.创建CorrelationData
	CorrelationData cd = new CorrelationData();
	// 2.给Future添加ConfirmCallback
	cd.getFuture().addCallback(new ListenableFutureCallback<CorrelationData.Confirm>() {
	  @Override
	  public void onFailure(Throwable ex) {
		// 2.1.Future发生异常时的处理逻辑，基本不会触发
		log.error("send message fail", ex);
	  }

	  @Override
	  public void onSuccess(CorrelationData.Confirm result) {
		// 2.2.Future接收到回执的处理逻辑，参数中的result就是回执内容
		if (result.isAck()) { // result.isAck()，boolean类型，true代表ack回执，false 代表 nack回执
		  log.debug("发送消息成功，收到 ack!");
		} else { // result.getReason()，String类型，返回nack时的异常描述
		  log.error("发送消息失败，收到 nack, reason : {}", result.getReason());
		  //在此处处理异常：补偿机制
		}
	  }
	});
	return cd;
  }


}
